#pragma once

#include "Thread.hpp"
#include "Task.hpp"
#include "Lock.hpp"
#include <iostream>
#include <vector>
#include <queue>
#include <pthread.h>
#include <cassert>
#include <ctime>
#include <cstdlib>

int myAdd(int x, int y)
{
    return x + y;
}

const int g_thread_num = 5;   // 线程池容量

template<class T>
class ThreadPool
{
private:
    bool IsEmpty()
    {
        return _block_queue.empty();
    }

    bool IsFull()
    {
        return _block_queue.size() == _capacity;
    }

    T getTask()
    {
        // std::cout << "size = " << _block_queue.size() << std::endl;
        T task = _block_queue.front();
        _block_queue.pop();
        return task;
    }

public:
    // 构造函数
    ThreadPool(int capacity = g_thread_num)
        : _capacity(capacity)
    {
        pthread_mutex_init(&_mtx, nullptr);
        pthread_cond_init(&_Empty, nullptr);
        pthread_cond_init(&_Full, nullptr);

        for(int i = 1; i <= _capacity; ++i)
        {
            // 创建线程，将指针插入_thread数组中
            _thread.push_back(new Thread(i, routine, (void*)this));
        }

        for(const auto& iter : _thread)
        {
            iter->start();   // 创建并运行线程函数
            // std::cout << iter->name() << " 线程启动成功!" << std::endl;
            logMessage(DEBUG, "%s 线程启动成功!", iter->name().c_str());
        }
    }

    // 开始运行线程
    // void run()
    // {
    //     for(const auto& iter : _thread)
    //     {
    //         iter->start();   // 创建并运行线程函数
    //         std::cout << iter->name() << " 线程启动成功!" << std::endl;
    //     }
    // }

    // 线程等待函数 -- 用于测试
    // void join()
    // {
    //     for(const auto& iter : _thread)
    //     {
    //         iter->join();
    //         std::cout << "等待线程成功" << std::endl;
    //     }
    // }

    // 向阻塞队列插入任务函数
    void push_task()
    {
        while(true)
        {
            int x = rand() % 20;
            int y = rand() % 20;

            // 申请锁
            {
                LockGuard lockGuard(&_mtx);
                while(IsFull()) pthread_cond_wait(&_Full, &_mtx);
                // std::cout << "制作任务成功：" << x << "+" << y << "=?" << std::endl;
                logMessage(DEBUG, "制作任务成功: %d+%d=?", x, y);
                T task(x, y, [](int x, int y)->int{
                    return x + y;
                });
                _block_queue.push(task);
                pthread_cond_signal(&_Empty);
            }

            sleep(1);
        }
    }

    // 析构函数
    ~ThreadPool()
    {
        for(const auto iter : _thread)
        {
            delete iter;
        }

        pthread_mutex_destroy(&_mtx);
        pthread_cond_destroy(&_Empty);
        pthread_cond_destroy(&_Full);
    }

private:
    // 线程函数 -- 从阻塞队列中获取任务
    static void* routine(void *args)
    {
        ThreadData *pdata = (ThreadData*)args;
        ThreadPool<T> *ptr = (ThreadPool<T>*)pdata->_args;

        T task;

        while(true)
        {
            {
                LockGuard lockGuard(&ptr->_mtx);  // 申请释放锁
                while(ptr->IsEmpty()) pthread_cond_wait(&ptr->_Empty, &ptr->_mtx);   // 如果阻塞队列没有数据就等待条件变量
                // std::cout << ptr->_capacity << std::endl;

                task = ptr->getTask();
                int ans = task();
                std::cout << "[" << pdata->_name << "] 任务处理完成: " << task.get_x() << "+" << task.get_y() << "=" << task() << std::endl;
                logMessage(DEBUG, "[%s]任务处理完成: %d+%d=%d", pdata->_name.c_str(), task.get_x(), task.get_y(), task());

                pthread_cond_signal(&ptr->_Full);
            }
        }

        return nullptr;

        // while(true)
        // {
        //     std::cout << "[" << pthread_self() << "]" << "aaa" << std::endl;
        //     sleep(1);
        // }
    }

    std::vector<Thread*> _thread;
    int _capacity;
    std::queue<T> _block_queue;
    pthread_mutex_t _mtx;
    pthread_cond_t _Empty;
    pthread_cond_t _Full;
};